package system

import (
	consts2 "MoSkeleton/config/consts"
	"MoSkeleton/framework"
	"MoSkeleton/framework/core/consts"
	"MoSkeleton/framework/core/dto/response"
	"MoSkeleton/framework/utils"
	"MoSkeleton/global"
	"MoSkeleton/models/system"
	"MoSkeleton/services"
	s1 "MoSkeleton/web/pogos/request/system"
	system2 "MoSkeleton/web/pogos/response/system"
	"MoSkeleton/web/v1/http/base"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/samber/lo"
	"go.uber.org/zap"
	"strconv"
	"strings"
	"time"
)

type SysUserCtrl struct {
	base.BaseCtrl
}

func (s *SysUserCtrl) GetCtrlTitle() string {
	msg, _ := utils.Translater.Translate(consts.TKey_TitleSysUserMsg)
	return msg
}

// GetUserPage 分页获取用户列表
// @Tags 用户管理
// @Summary 分页获取用户列表
// @Security ApiKeyAuth
// @Param data query system.SysUserPageReq true "分页获取岗位列表"
// @Success 200 {object} response.Response{data=response.PageResult} "{"code": 200, "data": [...]}"
// @Router /system/user/list [get]
func (s *SysUserCtrl) GetUserPage(c *gin.Context) {
	userPageReq := &s1.SysUserPageReq{}
	if err := c.ShouldBindQuery(userPageReq); err != nil {
		framework.MoLogger.Error("获取用户列表失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	userPageReq.ShouldBindParams(c)
	if userPageResp, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.GetUserPage(c, userPageReq); err != nil {
		framework.MoLogger.Error("获取用户列表失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_UserGetListFailMsg)
		return
	} else {
		response.SuccessAsI18n(c, consts.TKey_CommonGetListSuccessMsg, userPageResp)
	}
}

// GetUserDetailById 根据id获取用户信息
// @Tags 用户管理
// @Summary 根据id获取用户信息
// @Security ApiKeyAuth
// @Param id path string true "用户id"
// @Success 200 {object} response.Response{data=system2.SysUserDetailResp} "{"code": 200, "data": [...]}"
// @Router /system/user/{id} [get]
func (s *SysUserCtrl) GetUserDetailById(c *gin.Context) {
	userIdStr := c.Param("id")
	var userId *uint64
	if userIdStr != "" {
		useruId, err := strconv.ParseUint(userIdStr, 10, 64)
		if err != nil {
			framework.MoLogger.Error("参数错误", zap.Error(err))
			response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
			return
		}
		userId = &useruId
	}
	if userInfoResp, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.GetUserDetailById(c, userId); err != nil {
		framework.MoLogger.Error("获取用户信息失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_UserGetFailMsg)
	} else {
		response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, userInfoResp)
	}
}

// GetDeptTree 获取部门树
// @Tags 用户管理
// @Summary 获取部门树
// @Security ApiKeyAuth
// @Param data query system.SysDeptPageReq true "获取部门树"
// @Success 200 {object} response.Response{data=pogos.TreeSelect} "{"code": 200, "data": [...]}"
// @Router /system/user/deptTree [get]
func (s *SysUserCtrl) GetDeptTree(c *gin.Context) {
	deptReq := s1.SysDeptPageReq{}
	if err := c.ShouldBindQuery(&deptReq); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	if deptTreeResp, err := services.ServiceGroupInst.SystemGroupInst.SysDeptServiceInst.GetDeptTreeList(c, &deptReq); err != nil {
		framework.MoLogger.Error("获取部门树失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_DeptGetTreeFailMsg)
	} else {
		response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, deptTreeResp)
	}
}

// 登录信息
// @Tags 用户管理
// @Summary 登录信息
// @Security ApiKeyAuth
// @Param data query system.SysUserPageReq true "登录信息"
// @Success 200 {object} response.Response{data=system.SysUserInfoResp} "{"code": 200, "data": [...]}"
// @Router /system/user/getInfo [get]
func (s *SysUserCtrl) GetLoginUserInfo(c *gin.Context) {
	if sysUserinfoResp, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.GetLoginUserInfo(utils.GetUserIdFromGin(c)); err != nil {
		framework.MoLogger.Error("获取用户信息失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_UserGetFailMsg)
	} else {
		response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, sysUserinfoResp)
	}

}

// AddUser 添加用户
// @Tags 用户管理
// @Summary 添加用户
// @Security ApiKeyAuth
// @Param data body system.SysUserAddReq true "添加用户"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user [post]
func (s *SysUserCtrl) AddUser(c *gin.Context) {
	userAddReq := s1.SysUserAddReq{}
	if err := c.ShouldBindJSON(&userAddReq); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	userAddReq.CreatedBy = utils.GetUsernameFromGin(c)
	userAddReq.UpdatedBy = userAddReq.CreatedBy
	if ok, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.AddUser(c, &userAddReq); err != nil {
		framework.MoLogger.Error("添加用户失败", zap.Error(err))
		response.FailErrorWithCode(c, err, consts.CommCreatFailCode, consts.TKey_UserAddFailMsg)
	} else {
		response.SuccessAsI18n(c, consts.TKey_CommCreatSuccessMsg, ok)
	}
}

// UpdateUser 更新用户
// @Tags 用户管理
// @Summary 更新用户
// @Security ApiKeyAuth
// @Param data body system.SysUserUpdateReq true "更新用户"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user [put]
func (s *SysUserCtrl) UpdateUser(c *gin.Context) {
	userUpdateReq := s1.SysUserUpdateReq{}
	if err := c.ShouldBindJSON(&userUpdateReq); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	userUpdateReq.UpdatedBy = utils.GetUsernameFromGin(c)
	if ok, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.UpdateUser(c, &userUpdateReq); err != nil {
		framework.MoLogger.Error("更新用户失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommUpdateFailCode, consts.TKey_UserUpdateFailMsg)
		return
	} else {
		response.SuccessAsI18n(c, consts.TKey_CommUpdateSuccessMsg, ok)
	}
}

// ResetPassword 重置密码
// @Tags 用户管理
// @Summary 重置密码
// @Security ApiKeyAuth
// @Param data body system.ResetPasswordReq true "重置密码"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/resetPwd [put]
func (s *SysUserCtrl) ResetPassword(c *gin.Context) {
	resetPassword := s1.ResetPasswordReq{}
	if err := c.ShouldBindJSON(&resetPassword); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	if _, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.ResetPassword(c, &resetPassword); err != nil {
		framework.MoLogger.Error("重置密码失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommUpdateFailCode, consts.TKey_UserResetPasswdFailMsg)
		return
	}
	response.SuccessAsI18n(c, consts.TKey_UserResetPasswdSuccessMsg, "")
}

// ChangeStatus 更新用户状态
// @Tags 用户管理
// @Summary 更新用户状态
// @Security ApiKeyAuth
// @Param data body system.ChangeUserStatusReq true "更新用户状态"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/changeStatus [put]
func (s *SysUserCtrl) ChangeStatus(c *gin.Context) {
	req := s1.ChangeUserStatusReq{}
	if err := c.ShouldBindJSON(&req); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	req.UpdatedBy = utils.GetUsernameFromGin(c)
	if ok, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.ChangeStatus(c, &req); err != nil {
		framework.MoLogger.Error("更新用户状态失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommUpdateFailCode, consts.TKey_UserStatusUpdateFailMsg)
	} else if !ok {
		response.FailMsgAsI18n(c, consts.CommUpdateFailCode, consts.TKey_UserStatusUpdateFailMsg)
	} else {
		response.SuccessAsI18n(c, consts.TKey_UserStatusUpdateSuccessMsg, ok)
	}
}

// DeleteUser 删除用户
// @Tags 用户管理
// @Summary 删除用户
// @Security ApiKeyAuth
// @Param id path string true "id,删除用户"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/{ids} [delete]
func (s *SysUserCtrl) DeleteUser(c *gin.Context) {
	userIdsStr := c.Param("ids")
	if userIdsStr == "" {
		framework.MoLogger.Error("参数错误")
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	currentUserId := utils.GetUserIdFromGin(c)
	ids := strings.Split(userIdsStr, ",")

	if lo.Contains(ids, strconv.FormatUint(currentUserId, 10)) {
		response.FailMsgAsI18n(c, consts.CommDeleteFailCode, consts.TKey_UserOnlineDeleteFailMsg)
		return
	}
	var intIds = utils.StrsToUint64s(&ids)
	if ok, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.DeleteUsers(c, intIds); err != nil {
		framework.MoLogger.Error("删除用户失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommDeleteFailCode, consts.TKey_UserDeleteFailMsg)
	} else {
		response.SuccessAsI18n(c, consts.TKey_CommDeleteSuccessMsg, ok)
	}
}

// GetAuthRole 获取用户角色
// @Tags 用户管理
// @Summary 获取用户角色
// @Security ApiKeyAuth
// @Param id path string true "获取用户角色"
// @Success 200 {object} response.Response{data=map[string]interface{}} "{"code": 200, "data": [...]}"
// @Router /system/user/authRole/{id} [get]
func (s *SysUserCtrl) GetAuthRole(c *gin.Context) {
	userIdStr := c.Param("id")
	if userIdStr == "" {
		framework.MoLogger.Error("参数错误")
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	userId, err := strconv.ParseUint(userIdStr, 10, 64)
	if err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	var userItemResp *system2.SysUserItemResp
	if userItemResp, err = services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.GetDetail(userId); err != nil {
		framework.MoLogger.Error("获取用户失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_UserGetFailMsg)
		return
	}
	roleItemsResp, err := services.ServiceGroupInst.SystemGroupInst.SysRoleServiceInst.GetRolesByUserId(c, userId)
	if err != nil {
		framework.MoLogger.Error("获取角色失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_RoleGetFailMsg)
		return
	}
	if !system.IsUserAdmin(userId) {
		roleItemsResp = lo.Filter(roleItemsResp, func(item *system2.SysRoleItemResp, index int) bool {
			return !system.IsRoleAdmin(item.ID)
		})
	}
	resultMap := make(map[string]interface{})
	resultMap["user"] = userItemResp
	resultMap["roles"] = roleItemsResp
	response.SuccessAsI18n(c, consts.TKey_CommGetSuccessMsg, resultMap)
}

// UpdateAuthRole 更新用户角色
// @Tags 用户管理
// @Summary 更新用户角色
// @Security ApiKeyAuth
// @Param data body system.UpdateAuthRoleReq true "更新用户角色"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/authRole [put]
func (s *SysUserCtrl) UpdateAuthRole(c *gin.Context) {
	updateAuthRoleReq := s1.UpdateAuthRoleReq{}
	if err := c.ShouldBindQuery(&updateAuthRoleReq); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	if ok, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.UpdateAuthRole(c, &updateAuthRoleReq); err != nil {
		framework.MoLogger.Error("更新用户角色失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommUpdateFailCode, consts.TKey_UserAuthRoleFailMsg)
	} else {
		response.SuccessAsI18n(c, consts.TKey_UserAuthRoleSuccessMsg, ok)
	}
}

// GetProfile 获取用户配置信息
// @Tags 用户管理
// @Summary 获取用户配置信息
// @Security ApiKeyAuth
// @Success 200 {object} response.Response{data=system.UserProfileResp} "{"code": 200, "data": [...]}"
// @Router /system/user/profile [get]
func (s *SysUserCtrl) GetProfile(c *gin.Context) {
	userId := utils.GetUserIdFromGin(c)
	if userProfileResp, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.GetProfile(userId); err != nil {
		framework.MoLogger.Error("获取用户配置信息失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_UserProfileGetFailMsg)
	} else {
		response.SuccessAsI18n(c, consts.TKey_UserProfileGetSuccessMsg, userProfileResp)
	}
}

// UpdateProfile 更新用户配置信息
// @Tags 用户管理
// @Summary 更新用户配置信息
// @Security ApiKeyAuth
// @Param data body system.UpdateProfileReq true "更新用户配置信息"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/profile [put]
func (s *SysUserCtrl) UpdateProfile(c *gin.Context) {
	updateProfileReq := s1.UpdateProfileReq{}
	if err := c.ShouldBindJSON(&updateProfileReq); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	updateProfileReq.ID = utils.GetUserIdFromGin(c)
	if err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.UpdateProfile(&updateProfileReq); err != nil {
		framework.MoLogger.Error("更新用户配置信息失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommUpdateFailCode, consts.TKey_UserProfileUpdateFailMsg)
		return
	}
	response.SuccessAsI18n(c, consts.TKey_UserProfileUpdateSuccessMsg, "")
}

// UpdateProfilePassword 更新用户密码
// @Tags 用户管理
// @Summary 更新用户密码
// @Security ApiKeyAuth
// @Param data body system.UpdatePasswordReq true "更新用户密码"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/profile/updatePwd [put]
func (s *SysUserCtrl) UpdateProfilePassword(c *gin.Context) {
	updatePasswordReq := s1.UpdatePasswordReq{}
	if err := c.ShouldBindQuery(&updatePasswordReq); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	updatePasswordReq.ID = utils.GetUserIdFromGin(c)
	if err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.UpdateProfilePassword(&updatePasswordReq); err != nil {
		framework.MoLogger.Error("更新用户密码失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommUpdateFailCode, consts.TKey_UserPasswdUpdateFailMsg)
		return
	}
	response.SuccessAsI18n(c, consts.TKey_UserPasswdUpdateSuccessMsg, "")
}

// UpdateProfileAvatar 更新用户头像
// @Tags 用户管理
// @Summary 更新用户头像
// @Security ApiKeyAuth
// @Param data formData file true "更新用户头像"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/profile/avatar [post]
func (s *SysUserCtrl) UpdateProfileAvatar(c *gin.Context) {
	file, err := utils.GinLimitUploadFileSize(c, "avatarfile", framework.ConfigContainerInst.AppProperty.App.Gin.Multipart.MaxFileSize)
	if err != nil {
		return
	}
	id := utils.GetUserIdFromGin(c)
	if browserUploadFile, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.UpdateProfileAvatar(id, file); err != nil {
		global.MoLogger.Error("上传文件失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommUpdateFailCode, consts.TKey_UserAvatarUpdateFailMsg)
		return
	} else {
		result := make(map[string]interface{})
		result["imgUrl"] = browserUploadFile
		response.SuccessAsI18n(c, consts.TKey_UserAvatarUpdateSuccessMsg, result)
		return
	}
}

// ExportUser 导出用户
// @Tags 用户管理
// @Summary 导出用户
// @Security ApiKeyAuth
// @Param data query system.SysUserPageReq true "导出用户"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/export [post]
func (s *SysUserCtrl) ExportUser(c *gin.Context) {
	s.IgnoreLogResponseData(c)
	req := s1.SysUserPageReq{}
	if err := c.ShouldBind(&req); err != nil {
		framework.MoLogger.Error("参数错误", zap.Error(err))
		response.FailMsgAsI18n(c, consts.ValidatorParamsCheckFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	buf, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.Export(&req)
	if err != nil {
		framework.MoLogger.Error("导出用户失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_UserExportFailMsg)
		return
	}
	response.SuccessWithFileData(c, fmt.Sprintf(consts2.Excel_Export_User, time.Now().Unix()), buf)
}

// ImportTemplate 导出用户模板
// @Tags 用户管理
// @Summary 导出用户模板
// @Security ApiKeyAuth
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/importTemplate [post]
func (s *SysUserCtrl) ImportTemplate(c *gin.Context) {
	s.IgnoreLogResponseData(c)
	if buf, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.ImportTemplate(); err != nil {
		framework.MoLogger.Error("导出用户模板失败", zap.Error(err))
		response.FailErrorWithCodeAsI18n(c, err, consts.CommSelectFailCode, consts.TKey_UserTemplateExportFailMsg)
		return
	} else {
		response.SuccessWithFileData(c, fmt.Sprintf(consts2.Excel_Export_UserTemplate, time.Now().Unix()), buf)
	}
}

// ImportUser 导入用户
// @Tags 用户管理
// @Summary 导入用户
// @Security ApiKeyAuth
// @Param file formData file true "导入用户"
// @Success 200 {object} response.Response{msg=string} "{"code": 200, "data": [...]}"
// @Router /system/user/importData [post]
func (s *SysUserCtrl) ImportUser(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		framework.MoLogger.Error("导入用户失败", zap.Error(err))
		response.FailMsgAsI18n(c, consts.CommSelectFailCode, consts.TKey_ValidatorParamsCheckFailMsg)
		return
	}
	username := utils.GetUsernameFromGin(c)
	updateSupport := utils.StrToBoolDef(c.Query("updateSupport"), false)
	msg, err := services.ServiceGroupInst.SystemGroupInst.SysUserServiceInst.ImportUser(c, file, updateSupport, username)
	if err != nil {
		framework.MoLogger.Error("导入用户失败", zap.Error(err))
		response.FailErrorWithCode(c, err, consts.CommSelectFailCode, consts.TKey_UserImportFailMsg)
		return
	}
	response.SuccessAsI18n(c, consts.TKey_UserImportSuccessMsg, msg)
}
